#pragma once

#include <iostream>
#include <memory>
#include "Socket.hpp"
#include "Connection.hpp"
#include "HandlerConn.hpp"

using namespace socket_ns;

// 统一进行 listen socket 的管理工作
class Listener
{
private:
public:
    Listener(in_port_t port)
        : _port(port), _listen_socket(std::make_unique<TcpSocket>())
    {
        _listen_socket->BuildListenSocket(_port);
    }

    int GetSockfd()
    {
        return _listen_socket->GetSockfd();
    }

    void Accepter(Connection *conn)
    {
        errno = 0;
        while (true)
        {
            InetAddr addr;
            int code = 0;
            int sockfd = _listen_socket->Accepter(&addr, &code);
            if (sockfd >= 0)
            {
                LOG(INFO, "Get a new link, Client: [%s], sockfd: %d\n", addr.GetAddrStr().c_str(), sockfd);
                conn->GetReactor()->AddConnection(sockfd, EPOLLIN | EPOLLET, addr, NormalConnection);
            }
            else
            {
                if (code == EWOULDBLOCK)
                {
                    LOG(DEBUG, "All links are gotten\n");
                    break;
                }
                else if (code == EINTR)
                {
                    LOG(WARNING, "Signal interruption occurs\n");
                    continue;
                }
                else 
                {
                    LOG(ERROR, "Accept Error: %d -> %s\n", errno, strerror(errno));
                    break;
                }
            }
        }
    }

    ~Listener()
    {
    }

private:
    in_port_t _port;
    std::unique_ptr<Socket> _listen_socket;
};